/**
  ****************************************************************************************************
  * @file    fm33le0xxa_fl_exti.c
  * @author  FMSH Application Team
  * @brief   Src file of EXTI FL Module
  ****************************************************************************************************
  * @attention
  * Copyright (c) 2022, SHANGHAI FUDAN MICROELECTRONICS GROUP CO., LTD.(FUDAN MICROELECTRONICS./ FUDAN MICRO.)    
  * All rights reserved.    
  *    
  * Processor:                   FM33LE0xxA    
  * http:                        http://www.fmdevelopers.com.cn/    
  *    
  * Redistribution and use in source and binary forms, with or without    
  * modification, are permitted provided that the following conditions are met    
  *    
  * 1. Redistributions of source code must retain the above copyright notice,    
  *    this list of conditions and the following disclaimer.    
  *    
  * 2. Redistributions in binary form must reproduce the above copyright notice,    
  *    this list of conditions and the following disclaimer in the documentation    
  *    and/or other materials provided with the distribution.    
  *    
  * 3. Neither the name of the copyright holder nor the names of its contributors    
  *    may be used to endorse or promote products derived from this software    
  *    without specific prior written permission.    
  *    
  * 4. To provide the most up-to-date information, the revision of our documents     
  *    on the World Wide Web will be the most Current. Your printed copy may be      
  *    an earlier revision. To verify you have the latest information avaliable,    
  *    refer to: http://www.fmdevelopers.com.cn/.    
  *    
  * THIS SOFTWARE IS PROVIDED BY FUDAN MICRO "AS IS" AND ANY EXPRESSED     
    ORIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES     
    OF MERCHANTABILITY NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE    
    ARE DISCLAIMED.IN NO EVENT SHALL FUDAN MICRO OR ITS CONTRIBUTORS BE LIABLE     
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL     
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS     
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER    
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,     
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY WAY OUT OF THE     
    USE OF THIS SOFTWARE, EVEN IF ADVISED OFTHE POSSIBILITY OF SUCH DAMAGE.    
  ****************************************************************************************************
  */


/* Includes ------------------------------------------------------------------*/
#include "fm33le0xxa_fl.h"

/** @addtogroup FM33LE0XXA_FL_Driver
  * @{
  */

/** @addtogroup EXTI
  * @{
  */

#ifdef FL_EXTI_DRIVER_ENABLED

/* Private macros ------------------------------------------------------------*/
/** @addtogroup EXTI_FL_Private_Macros
  * @{
  */

#define IS_EXTI_ALL_INSTANCE(INSTANCE)             (((INSTANCE) == FL_GPIO_EXTI_LINE_0)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_1)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_2)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_3)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_4)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_5)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_6)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_7)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_8)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_9)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_10)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_11)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_12)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_13)||\
                                                    ((INSTANCE) == FL_GPIO_EXTI_LINE_14))

#define IS_EXTI_CLK_SOURCE(__VALUE__)              (((__VALUE__) == FL_RCC_EXTI_CLK_SOURCE_HCLK)||\
                                                    ((__VALUE__) == FL_RCC_EXTI_CLK_SOURCE_LSCLK))

#define IS_EXTI_INPUT_GROUP(__VALUE__)             (((__VALUE__) == FL_GPIO_EXTI_INPUT_GROUP0)||\
                                                    ((__VALUE__) == FL_GPIO_EXTI_INPUT_GROUP1)||\
                                                    ((__VALUE__) == FL_GPIO_EXTI_INPUT_GROUP2)||\
                                                    ((__VALUE__) == FL_GPIO_EXTI_INPUT_GROUP3))

#define IS_EXTI_TRIG_EDGE(__VALUE__)               (((__VALUE__) == FL_GPIO_EXTI_TRIGGER_EDGE_RISING)||\
                                                    ((__VALUE__) == FL_GPIO_EXTI_TRIGGER_EDGE_FALLING)||\
                                                    ((__VALUE__) == FL_GPIO_EXTI_TRIGGER_EDGE_BOTH)||\
                                                    ((__VALUE__) == FL_GPIO_EXTI_TRIGGER_EDGE_DISABLE))

#define IS_EXTI_FILTER(__VALUE__)                  (((__VALUE__) == FL_ENABLE)||\
                                                    ((__VALUE__) == FL_DISABLE))

/**
  * @}
  */

/* Private consts ------------------------------------------------------------*/
/** @addtogroup EXTI_FL_Private_Consts
  * @{
  */

typedef void (*pSetExtiLineFunc)(GPIO_COMMON_Type *, uint32_t);
static const pSetExtiLineFunc setExtiLineFuncs[] =
{
    FL_GPIO_SetExtiLine0,
    FL_GPIO_SetExtiLine1,
    FL_GPIO_SetExtiLine2,
    FL_GPIO_SetExtiLine3,
    FL_GPIO_SetExtiLine4,
    FL_GPIO_SetExtiLine5,
    FL_GPIO_SetExtiLine6,
    FL_GPIO_SetExtiLine7,
    FL_GPIO_SetExtiLine8,
    FL_GPIO_SetExtiLine9,
    FL_GPIO_SetExtiLine10,
    FL_GPIO_SetExtiLine11,
    FL_GPIO_SetExtiLine12,
    FL_GPIO_SetExtiLine13,
    FL_GPIO_SetExtiLine14,
};

typedef void (*pSetTrigEdgeFunc)(GPIO_COMMON_Type *, uint32_t, uint32_t);
static const pSetTrigEdgeFunc setTrigEdgeFuncs[] =
{
    FL_GPIO_SetTriggerEdge,
};

/**
  * @}
  */

/** @addtogroup EXTI_FL_EF_Init
  * @{
  */

/**
  * @brief  EXTI通用配置设置
  *
  * @param  EXTI_CommonInitStruct 指向 @ref FL_EXTI_CommonInitTypeDef 类型的结构体，它包含EXTI外设通用配置信息
  *
  * @retval ErrorStatus枚举值
  *         -FL_FAIL 配置过程发生错误
  *         -FL_PASS EXTI配置成功
  */
FL_ErrorStatus FL_EXTI_CommonInit(FL_EXTI_CommonInitTypeDef *EXTI_CommonInitStruct)
{
    assert_param(IS_EXTI_CLK_SOURCE(EXTI_CommonInitStruct->clockSource));
    /* 使能IO时钟寄存器总线时钟 */
    FL_RCC_EnableGroup1BusClock(FL_RCC_GROUP1_BUSCLK_PAD);
    /* 使能并配置外部中断时钟源 */
    FL_RCC_EnableGroup1OperationClock(FL_RCC_GROUP1_OPCLK_EXTI);
    FL_RCC_SetEXTIClockSource(EXTI_CommonInitStruct->clockSource);
    return FL_PASS;
}

/**
  * @brief  复位EXTI通用配置设置
  *
  * @retval 执行结果
  *         -FL_PASS 外设寄存器值恢复复位值
  *         -FL_FAIL 未成功执行
  */
FL_ErrorStatus FL_EXTI_CommonDeinit(void)
{
    /* 关闭外部中断时钟源 */
    FL_RCC_DisableGroup1OperationClock(FL_RCC_GROUP1_OPCLK_EXTI);
    return FL_PASS;
}

/**
  * @brief  设置 EXTI_CommonInitStruct 为默认配置
  * @param  EXTI_CommonInitStruct 指向需要将值设置为默认配置的结构体 @ref FL_EXTI_CommonInitTypeDef 结构体
  *
  * @retval None
  */
void FL_EXTI_CommonStructInit(FL_EXTI_CommonInitTypeDef *EXTI_CommonInitStruct)
{
    EXTI_CommonInitStruct->clockSource = FL_RCC_EXTI_CLK_SOURCE_LSCLK;
}

/**
  * @brief  EXTI配置设置
  *
  * @param  extiLineX 外设入口地址
  * @param  EXTI_InitStruct 指向 @ref FL_EXTI_InitTypeDef 类型的结构体，它包含EXTI外设配置信息
  *
  * @retval ErrorStatus枚举值
  *         -FL_FAIL 配置过程发生错误
  *         -FL_PASS EXTI配置成功
  */
FL_ErrorStatus FL_EXTI_Init(uint32_t extiLineX, FL_EXTI_InitTypeDef *EXTI_InitStruct)
{
    uint8_t extiLineId;
    uint32_t tmpExtiLineX;
		  uint32_t i = 0;
	  /* 通过内核时钟计算200us延时的计数个数 */
	  uint32_t temp = SystemCoreClock/1000000*200 ;
    /* 检查参数合法性 */
    assert_param(IS_EXTI_ALL_INSTANCE(extiLineX));
    assert_param(IS_EXTI_INPUT_GROUP(EXTI_InitStruct->input));
    assert_param(IS_EXTI_TRIG_EDGE(EXTI_InitStruct->triggerEdge));
    assert_param(IS_EXTI_FILTER(EXTI_InitStruct->filter));
    /* 获取EXTI中断线对应id号 */
    tmpExtiLineX = extiLineX;
    for(extiLineId = 0; tmpExtiLineX != FL_GPIO_EXTI_LINE_0; tmpExtiLineX >>= 1, extiLineId++);
    /* 设置中断线连接的IO */
    setExtiLineFuncs[extiLineId](GPIO, EXTI_InitStruct->input << (2 * extiLineId));
    /* 设置数字滤波 */
    EXTI_InitStruct->filter == FL_ENABLE ? FL_GPIO_EnableDigitalFilter(GPIO, extiLineX) : FL_GPIO_DisableDigitalFilter(GPIO, extiLineX);
    /* 设置中断线触发边沿 */
    setTrigEdgeFuncs[extiLineId / 16](GPIO, extiLineX, EXTI_InitStruct->triggerEdge);
    /* 延时需要大于5个32K的周期 */
		for(i=0;i<temp;i++)
		{
			__NOP();
		}
    /* 清除外部中断标志 */
    FL_GPIO_ClearFlag_EXTI(GPIO, extiLineX);
    /* 清除中断挂起 */
    NVIC_ClearPendingIRQ(GPIO_IRQn);
    return FL_PASS;
}

/**
  * @brief  复位EXTI配置设置
  *
  * @retval ErrorStatus枚举值
  *         -FL_FAIL 发生错误
  *         -FL_PASS EXTI设置复位成功
  */
FL_ErrorStatus FL_EXTI_DeInit(uint32_t extiLineX)
{
    uint8_t extiLineId;
    uint32_t tmpExtiLineX;
    /* 检查参数合法性 */
    assert_param(IS_EXTI_ALL_INSTANCE(extiLineX));
    /* 获取EXTI中断线对应id号 */
    tmpExtiLineX = extiLineX;
    for(extiLineId = 0; tmpExtiLineX != FL_GPIO_EXTI_LINE_0; tmpExtiLineX >>= 1, extiLineId++);
    /* 清除外部中断标志 */
    FL_GPIO_ClearFlag_EXTI(GPIO, extiLineX);
    /* 中断线触发边沿禁止 */
    setTrigEdgeFuncs[extiLineId / 16](GPIO, extiLineX, FL_GPIO_EXTI_TRIGGER_EDGE_DISABLE);
    /* 禁止数字滤波 */
    FL_GPIO_DisableDigitalFilter(GPIO, extiLineX);
    return FL_PASS;
}

/**
  * @brief  设置 EXTI_InitStruct 为默认配置
  * @param  EXTI_InitStruct 指向需要将值设置为默认配置的结构体 @ref FL_EXTI_InitTypeDef 结构体
  *
  * @retval None
  */
void FL_EXTI_StructInit(FL_EXTI_InitTypeDef *EXTI_InitStruct)
{
    EXTI_InitStruct->filter = FL_DISABLE;
    EXTI_InitStruct->input = FL_GPIO_EXTI_INPUT_GROUP0;
    EXTI_InitStruct->triggerEdge = FL_GPIO_EXTI_TRIGGER_EDGE_RISING;
}

/**
  * @}
  */

#endif /* FL_EXTI_DRIVER_ENABLED */

/**
  * @}
  */

/**
  * @}
  */

/********************** (C) COPYRIGHT Fudan Microelectronics **** END OF FILE ***********************/
